#include <getopt.h>

#include <string>

#include "sym-info-table.h"
#include "sym-name-table.h"
#include "sym-find-print.h"
#include "string-util.h"

using std::string;

void SymFindPrint::init(int argc,char **argv)
{
    detail_info = false;
    print_language = false;
    printed_symbol_num = 0;
    symname_bak.reset();

    struct option options[] = {
        {"full",no_argument,0,'F'},
        {"language",required_argument,0,'L'},
        {NULL,0,0,0}
    };
    optind = 0;
    opterr = 0;
    int l_opt_num = 0;
    int getopt_ret;
    while ((getopt_ret = getopt_long(argc,argv,"-FL:",options,0)) != -1) {
        switch (getopt_ret) {
        case 'F':
            detail_info = true;
            break;
        case 'L':
            ++l_opt_num;
            break;
        default:
            break;
        }
    }
    print_language = (l_opt_num == 1 ? false : true);
    return ;
}

void SymFindPrint::print(SymInfoTable::id_t id,std::shared_ptr<SymName> symname)
{
    ++printed_symbol_num;
    if (printed_symbol_num == 1) {
        id_bak = id;
        symname_bak = symname;
    } else {
        if (symname_bak) {
            do_print(id_bak,symname_bak);
            symname_bak.reset();
        }
        do_print(id,symname);
    }
    return ;
}

void SymFindPrint::flush()
{
    if (symname_bak) {
        do_print(id_bak,symname_bak);
        symname_bak.reset();
    }
    return ;
}


namespace {

// 返回 buf 的第一行(不带换行符),若 buf 仅有 1 行,则返回全部内容.
string firstLine(const string &buf)
{
    auto newline_pos = buf.find_first_of('\n');
    if (newline_pos == string::npos)
        return buf;
    return buf.substr(0,newline_pos);
}

}

void SymFindPrint::do_print(SymInfoTable::id_t id,std::shared_ptr<SymName> symname)
{
    string symbol_name = symname->name();
    string output_content;
    SymInfo syminfo;

    SymInfoTable &info_table = SymInfoTable::instance();
    info_table.get(id,syminfo);

    if (printed_symbol_num == 1 || detail_info) {
        output_content.append(symbol_name);
        if (print_language) {
            output_content.append(" (");
            output_content.append(syminfo.language());
            output_content.append(1,')');
        }
        output_content.append(1,'\n');
        output_content.append(syminfo.doc());
    } else {
        if (print_language) {
            output_content.append(syminfo.language());
            output_content.append(1,';');
        }
        output_content.append(symbol_name);
        output_content.append(1,';');
        output_content.append(firstLine(syminfo.doc()));
    }
    trim(output_content);
    puts(output_content.c_str());
    return ;
}
